package com.weixing.mall.provider.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.weixing.mall.core.utils.CommonUtil;
import com.weixing.mall.provider.api.model.dto.UserDto;
import com.weixing.mall.provider.api.model.vo.*;
import com.weixing.mall.provider.mapper.DeptMapper;
import com.weixing.mall.provider.mapper.RoleUserMapper;
import com.weixing.mall.provider.mapper.UserMapper;
import com.weixing.mall.provider.model.domain.Dept;
import com.weixing.mall.provider.model.domain.Menu;
import com.weixing.mall.provider.model.domain.RoleUser;
import com.weixing.mall.provider.model.domain.User;
import com.weixing.mall.provider.model.dto.sys.ResetPasswordDto;
import com.weixing.mall.provider.model.dto.sys.SysUserDto;
import com.weixing.mall.provider.model.enums.IsLeafEnum;
import com.weixing.mall.provider.model.enums.WhetherEnum;
import com.weixing.mall.provider.model.enums.sys.MenuTypeEnum;
import com.weixing.mall.provider.model.enums.sys.SysFlag;
import com.weixing.mall.provider.model.query.SysUserQuery;
import com.weixing.mall.provider.model.vo.FrontUserVo;
import com.weixing.mall.provider.model.vo.sys.SysUserRoleVo;
import com.weixing.mall.provider.service.IUserService;
import com.weixing.mall.provider.support.constant.CmsConst;
import jodd.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统模块-后台用户表 服务实现类
 * </p>
 *
 * @author Small
 * @since 2019-11-18
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RoleUserMapper roleUserMapper;
    @Autowired
    private DeptMapper deptMapper;

    @Override
    public IPage<SysUserVo> selectOfPage(Page initMpPage, SysUserQuery sysUserQuery) {
        return baseMapper.selectOfPage(initMpPage, sysUserQuery);
    }

    @Override
    public User findByLoginName(String loginName) {
        return getOne(new QueryWrapper<User>().eq("login_name", loginName));
    }

    @Override
    public User findByMobile(String mobile) {
        return getOne(new QueryWrapper<User>().eq("mobile", mobile));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(SysUserDto sysUserDto) {
        User sysUser = new User();
        BeanUtils.copyProperties(sysUserDto, sysUser);
        sysUser.setGender(sysUserDto.getGender().getValue());
        sysUser.setIsEnable(sysUserDto.getIsEnable().getValue());
        sysUser.setUserStar(sysUserDto.getUserStar().getValue());
        if (null == sysUserDto.getId()) {
            sysUser.setLoginPwd(CommonUtil.encryptPassword(sysUserDto.getLoginPwd()));
            sysUser.setIsPwdChanged(WhetherEnum.NO.getValue());
            save(sysUser);
        } else {
            sysUser.setLoginName(null);
            updateById(sysUser);
        }

        Long userId = sysUser.getId();
        // 1、先删除原有角色记录
        roleUserMapper.deleteByUserId(sysUser.getId());
        // 2、保存新的角色记录
        Long[] roles = sysUserDto.getRoles();
        System.out.println(sysUser.toString() + "----");
        if (roles.length > 0) {
            RoleUser sysRoleUser;
            ArrayList<RoleUser> list = Lists.newArrayList();
            for (Long roldId : roles) {
                sysRoleUser = new RoleUser();
                sysRoleUser.setSysFlag(SysFlag.SYS.getValue());
                sysRoleUser.setRoleId(roldId);
                sysRoleUser.setUserId(userId);
                list.add(sysRoleUser);
            }
            for (RoleUser roleUser : list) {
                roleUserMapper.insert(roleUser);
            }
        }
    }

    @Override
    public void resetPwd(User user) {
        baseMapper.resetPwd(user.getId(), new BCryptPasswordEncoder().encode(CmsConst.DEFAULT_PWD));
    }

    @Override
    public void changeEnable(Long userId, Integer value) {
        baseMapper.changeEnable(userId, value);
    }

    @Override
    public SysUserEditVo selectSysUserEditVoById(long id) {
        SysUserEditVo editVo = baseMapper.selectSysUserEditVoById(id);
        List<RoleUser> sysRoleUserList = roleUserMapper.selectByUserId(id);
        ArrayList<Long> roles = Lists.newArrayList();
        if (!sysRoleUserList.isEmpty()) {
            for (RoleUser item : sysRoleUserList) {
                roles.add(item.getRoleId());
            }
        }
        Dept sysDept = deptMapper.selectById(editVo.getDeptId());
        String deptPath = sysDept.getDeptPath();
        String[] split = deptPath.split("\\|");
        ArrayList<Long> deptPathList = Lists.newArrayList();
        for (String s : split) {
            deptPathList.add(Long.parseLong(s));
        }
        editVo.setRoles(roles);
        editVo.setDeptPath(deptPathList);
        return editVo;
    }

    @Override
    public List<SysUserRoleVo> selectSysUserByRoleCode(String roleCode,Integer isEnable) {
        List<String> roleCodeList = Lists.newArrayList();
        /*roleCodeList.add("admin");
        roleCodeList.add("developer");*/
        if(StrUtil.isNotEmpty(roleCode)){
            roleCodeList.add(roleCode);
        }
        return baseMapper.selectSysUserByRoleCode(roleCodeList,isEnable);
    }

    @Override
    public Set<String> loadUserAuthorities(Long userId) {
        System.out.println("未走缓存");
        List<String> menuUrls = roleUserMapper.selectUserMenu(userId);
        Set<String> sets = new HashSet<>(menuUrls);
        return sets;
//        List<GrantedAuthority> authList = Lists.newArrayList();
//        GrantedAuthority grantedAuthority = null;
//        for (String url : sets) {
//            grantedAuthority = new MySimpleGrantedAuthority(url);
//            authList.add(grantedAuthority);
//        }
//        return authList;
    }

    @Override
    public List<VueAuthorizeBean> loadVueAuthorize(Long userId, SysFlag sysFlag) {
        List<Menu> menus = roleUserMapper.selectUserMenus(userId,sysFlag.getValue());

        Set<Menu> menuSet = new HashSet<>(menus);

        List<VueAuthorizeBean> vueAuthList = Lists.newArrayList();
        // 过滤出一级菜单
        List<Menu> menu1 = menuSet.stream().filter((Menu m) -> m.getMenuType().equals(MenuTypeEnum.MENU_LEVEL_1.getValue())).collect(Collectors.toList());
        fillVueAuthBean(menuSet, menu1, vueAuthList);
        return vueAuthList;
    }

    @Override
    public void changeAvatar(String avatar, Long uid) {
        User sysUser = new User();
        sysUser.setId(uid);
        sysUser.setAvator(avatar);
        updateById(sysUser);
    }

    @Override
    public void changePassword(ResetPasswordDto dto, User sysUser) {
        User newUser = new User();
        newUser.setId(sysUser.getId());
        newUser.setLoginPwd(CommonUtil.encryptPassword(dto.getNewPassword()));
        if (WhetherEnum.NO.getValue().equals(sysUser.getIsPwdChanged())) {
            newUser.setIsPwdChanged(WhetherEnum.YES.getValue());
        }
        updateById(newUser);
    }

    @Override
    public List<RoleVo> getRoleById(Long id) {
        return baseMapper.getRoleById(id);
    }

    @Override
    public FrontUserVo querySysUser(Long id) {
        return baseMapper.querySysUser(id);
    }

    @Override
    public FrontUserVo queryMemberUser(Long id) {
        return baseMapper.queryMemberUser(id);
    }

    @Override
    public List<KefuVo> loadKefu() {
        return baseMapper.loadKefu();
    }

    @Override
    public KefuVo loadKefuById(Long id) {
        return baseMapper.loadKefuById(id);
    }

    @Override
    public Long createUser(UserDto userDto) {
        User sysUser = new User();
        BeanUtils.copyProperties(userDto, sysUser);
        sysUser.setLoginPwd(CommonUtil.encryptPassword(userDto.getLoginPwd()));
        sysUser.setIsPwdChanged(WhetherEnum.NO.getValue());
        save(sysUser);

        Long userId = sysUser.getId();
        // 1、先删除原有角色记录
        roleUserMapper.deleteByUserId(sysUser.getId());
        // 2、保存新的角色记录
        Long[] roles = userDto.getRoles();
        System.out.println(sysUser.toString() + "----");
        if (roles.length > 0) {
            RoleUser sysRoleUser;
            ArrayList<RoleUser> list = Lists.newArrayList();
            for (Long roldId : roles) {
                sysRoleUser = new RoleUser();
                sysRoleUser.setRoleId(roldId);
                sysRoleUser.setUserId(userId);
                list.add(sysRoleUser);
            }
            for (RoleUser roleUser : list) {
                roleUserMapper.insert(roleUser);
            }
        }
        return sysUser.getId();
    }

    @Override
    public IPage<KefuVo> loadKefuOfPage(Page initMpPage) {
        return baseMapper.loadKefuOfPage(initMpPage);
    }

    @Override
    public KefuVo loadKefuByLoginName(String loginName) {
        return baseMapper.loadKefuByLoginName(loginName);
    }

    @Override
    public void updateCid(String mobile, Long mid) {
        User user = new User();
        user.setId(mid);
        user.setCid(mobile);
        updateById(user);
    }

    private void fillVueAuthBean(Set<Menu> src, List<Menu> roots, List<VueAuthorizeBean> vueAuthList) {
        if (null != roots && !roots.isEmpty()) {
            for (Menu root : roots) {

                // 过滤子节点
                Integer menuType = root.getMenuType();
                List<Menu> children = Lists.newArrayList();
                if (!menuType.equals(MenuTypeEnum.MENU_BTN.getValue()) && !menuType.equals(MenuTypeEnum.MENU_HREF.getValue())) {
                    children = src.stream().filter((Menu m) -> m.getParentId().longValue() == root.getId().longValue()).collect(Collectors.toList());
                }
                // 如果vuePath不为空
                if (StringUtil.isNotBlank(root.getVuePath())) {
                    VueAuthorizeBean vb = new VueAuthorizeBean();
                    vb.setVuePath(root.getVuePath());
                    //是否是叶子节点
                    if (root.getVueIsLeaf().equals(IsLeafEnum.YES.getValue())) {
                        if (!children.isEmpty()) {
                            List<String> btns = Lists.newArrayList();
                            for (Menu m : children) {
                                if (m.getMenuType().equals(MenuTypeEnum.MENU_BTN.getValue())) {
                                    btns.add(m.getVuePath());
                                }
                            }
                            vb.setBtn(btns);
                        }
                    }
                    vueAuthList.add(vb);
                }
                fillVueAuthBean(src, children, vueAuthList);
            }
        }
    }

    @Override
    public List<SysUserRoleVo> selectSysUserByRoleCode(List<String> roleCode, Integer isEnable) {
        return baseMapper.selectSysUserByRoleCode(roleCode,isEnable);
    }

    @Override
    public List<VueAuthorizeBean> loadVueAuthorizeByRoleCode(String roleCode, SysFlag sysFlag) {
        List<Menu> menus = roleUserMapper.selectUserMenusByRoleCode(roleCode,sysFlag.getValue());

        Set<Menu> menuSet = new HashSet<>(menus);

        List<VueAuthorizeBean> vueAuthList = Lists.newArrayList();
        // 过滤出一级菜单
        List<Menu> menu1 = menuSet.stream().filter((Menu m) -> m.getMenuType().equals(MenuTypeEnum.MENU_LEVEL_1.getValue())).collect(Collectors.toList());
        fillVueAuthBean(menuSet, menu1, vueAuthList);
        return vueAuthList;
    }
}
